<?php

namespace lico\Runtime;

use Middleware\Index as MiddleWareIndex;

/**
 * 框架生命周期执行队列
 */

use lico\Container;

class RunQueue
{
    //容器执行队列
    protected static $_queue = [

        'lico\Runtime\Build',
        'lico\Runtime\Request',
        'lico\Runtime\Route',
        'lico\Runtime\Config',
        'lico\Runtime\App',
        'lico\Runtime\Response',

    ];

    protected static $_event; //before,after

    public static function runTime()
    {

        ob_start(); //开启页面缓存
        foreach (self::$_queue as $key => $value) {
            $init = self::middlewareRun($value);//中间件，主函数执行
            if (!$init) {
                // break;
                throw new \Exception($value . "初始化失败", 1);
            }
        }
    }


    /**
     * 执行钩子
     *
     * @param [type] $eventMain 事件执行的主体
     * @param string $event 事件
     * @return void
     */
    public static function middlewareRun($runClass)
    {
        $Middleware = Container::getBowl('Middleware\Index', [], true);
        $eventQueue = $Middleware->_event;

        //主函数
        $class = Container::getBowl($runClass, [], true);
        $closure = function () use ($class) {
            return $init = $class->run();
        };

        $event = basename($runClass, '\\');
        if (!empty($eventQueue[$event])) {
            foreach ($eventQueue[$event] as $type => $method) {
                $closure = self::middlewareCallBack(
                    $closure, 
                    function () use ($Middleware, $method) {
                        return $Middleware->$method();
                    }, 
                    $type
                );
            }
            return $closure();
        } else {
            return $init = $class->run();
        }
    }

    /**
     * 中间件闭包
     */
    public static function middlewareCallBack($mainMethod, $middleMethod = null, $type = null)
    {
        $callFunc = function ($param = null) use ($mainMethod, $middleMethod, $type) {
            if ($type == 'before') {
                $middleMethod($param);
            }
            $return = $mainMethod();
            if ($type == 'after') {
                $middleMethod($param);
            }
            return $return;
        };
        return $callFunc;
    }
}
